home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigantic Games 2
/
Gigantic Games 2.iso
/
pc
/
_t_
/
tetris
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-23
|
12KB
|
454 lines
/*
Copyright (c) 1992, Trevor Smigiel. All rights reserved.
(I hope Commodore doesn't mind that I borrowed their copyright notice.)
The source and executable code of this program may only be distributed in free
electronic form, via bulletin board or as part of a fully non-commercial and
freely redistributable diskette. Both the source and executable code (including
comments) must be included, without modification, in any copy. This example may
not be published in printed form or distributed with any commercial product.
This program is provided "as-is" and is subject to change; no warranties are
made. All use is at your own risk. No liability or responsibility is assumed.
*/
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <intuition/icclass.h>
#include <clib/macros.h>
#include <stdio.h>
#include "tetris.h"
#include "con_input.h"
/* */
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include "Tetris_protos.h"
#include "TetrisImages_protos.h"
UBYTE *vers = "$VER: Tetris 1.0";
void KeyTask(void);
void JoyTask(void);
#define MAX_PLAYERS 3
#define STACK_SIZE 10000L
void (*TaskEntries[])(void) = { KeyTask, KeyTask, KeyTask, JoyTask };
/* Each switch on a joystick corrosponds to a bit in cd_State */
/* The index of the character in the key string, is the same bit in cd_State */
/* bit 6 5 4 3 2 1 0 */
/* mb rb lb u d l r */
char *ControlKeys[] = {
"\x22\x20\x21\x10\x11", /* and the same for these */
"\x28\x26\x27\x16\x17", /* ditto */
"\x2f\x2d\x2e\x1e\x3e", /* These keys are only good for Tetris */
NULL, /* joystick */
};
char *ControlUsage[] = {
"keyboard: w - rotate, a - left, s - down, d - right.",
"keyboard: i - rotate, j - left, k - down, l - right.",
"numberpad: 8 - rotate, 4 - left, 5 - down, 6 - right.",
"joystick: up/button - rotate, left - left, down - down, right - right.",
};
struct ControlData Controls[MAX_PLAYERS];
struct Screen *Screen;
struct Window *Window;
struct Gadget *Gadgets;
struct MsgPort *tetris_MsgPort;
struct MsgPort *timer_MsgPort;
struct timerequest *timer_IORequest;
struct MinList Boards = {(struct MinNode *)&Boards.mlh_Tail, NULL, (struct MinNode *)&Boards};
WORD heights[2];
WORD PWidth = 0;
WORD PHeight = 0;
WORD NumPlayers = 0;
WORD Players = 1;
WORD Level = 0;
WORD BSize = 8;
WORD XSize = 16;
WORD YSize = 16;
WORD Depth = 2;
WORD NoWaitLevel = 0;
WORD Flags = 0;
#define GFLG_QUIT 0x0001
void
event_handler(void)
{
struct TBoard *board;
ULONG signals, signaled;
ULONG timer_signal, window_signal, tetris_signal;
WORD paused = 0;
int i, gameover, nextlevel;
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task) {
board = Controls[i].cd_Board;
StartLevel(board, Level);
}
}
tetris_signal = (1 << tetris_MsgPort->mp_SigBit);
timer_signal = (1 << timer_MsgPort->mp_SigBit);
window_signal = (1 << Window->UserPort->mp_SigBit);
signals = tetris_signal | timer_signal | window_signal | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F;
while (NumPlayers > 0) {
signaled = Wait(signals);
if (signaled & SIGBREAKF_CTRL_C)
Flags |= GFLG_QUIT;
if (signaled & SIGBREAKF_CTRL_F) { /* Child is done */
for (i = 0; i < Players; i++) {
if ((Controls[i].cd_Task != NULL) && (Controls[i].cd_MsgPort == NULL)) {
FreeBoard(Controls[i].cd_Board);
DeleteTask(Controls[i].cd_Task);
Controls[i].cd_Board = NULL;
Controls[i].cd_Task = NULL;
NumPlayers--;
}
}
}
if (signaled & timer_signal) {
GetMsg(timer_MsgPort); /* There is only one message -- timer_IORequest */
timer_IORequest->tr_time.tv_secs = 0;
timer_IORequest->tr_time.tv_micro = UPDATE_TIME;
SendIO((struct IORequest *)timer_IORequest);
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task)
UpdateTetris(Controls[i].cd_Board);
}
}
if (signaled & tetris_signal) {
struct ControlMsg *cmsg;
while (cmsg = (struct ControlMsg *)GetMsg(tetris_MsgPort)) {
if ((!paused) && (board = cmsg->cm_CData->cd_Board)) {
int state = cmsg->cm_State;
if (state & 1)
MoveTetris(board, COMMAND_RIGHT);
else if (state & 2)
MoveTetris(board, COMMAND_LEFT);
if (state & 4)
MoveTetris(board, COMMAND_DOWN);
else if (state & 8)
MoveTetris(board, COMMAND_ROTATE); /* Two rotates to accomodate joysticks */
if (state & 0x70) /* Any button */
MoveTetris(board, COMMAND_ROTATE);
}
ReplyMsg((struct Message *)cmsg);
}
}
if (signaled & window_signal) {
struct IntuiMessage *msg;
while (msg = (struct IntuiMessage *)GetMsg(Window->UserPort)) {
switch (msg->Class) {
case IDCMP_CHANGEWINDOW:
case IDCMP_ACTIVEWINDOW:
if (Window->Height != heights[paused]) {
if (paused) {
paused = 0;
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task)
Signal(Controls[i].cd_Task, SIGBREAKF_CTRL_E);
}
SetWindowTitles(Window, "Tetris", "Tetris");
if (CheckIO((struct IORequest *) timer_IORequest)) {
timer_IORequest->tr_time.tv_secs = 0;
timer_IORequest->tr_time.tv_micro = UPDATE_TIME;
SendIO((struct IORequest *)timer_IORequest);
}
} else {
case IDCMP_INACTIVEWINDOW:
paused = 1;
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task)
Signal(Controls[i].cd_Task, SIGBREAKF_CTRL_D);
}
SetWindowTitles(Window, "Paused", "Tetris");
if (!CheckIO((struct IORequest *) timer_IORequest)) {
AbortIO((struct IORequest *) timer_IORequest);
WaitIO((struct IORequest *) timer_IORequest);
SetSignal(0, timer_signal);
}
}
}
break;
case IDCMP_REFRESHWINDOW:
BeginRefresh(Window);
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task)
DrawBoard(Controls[i].cd_Board);
}
EndRefresh(Window, TRUE);
break;
case IDCMP_CLOSEWINDOW:
Flags |= GFLG_QUIT;
break;
default:
break;
}
ReplyMsg((struct Message *)msg);
}
}
if (Flags & GFLG_QUIT) {
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task)
Signal(Controls[i].cd_Task, SIGBREAKF_CTRL_C);
}
paused = 1;
if (!CheckIO((struct IORequest *) timer_IORequest)) {
AbortIO((struct IORequest *) timer_IORequest);
WaitIO((struct IORequest *) timer_IORequest);
SetSignal(0, timer_signal);
}
}
if (!paused) {
nextlevel = gameover = 0;
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task) {
board = Controls[i].cd_Board;
if (board->flags & TETF_GAMEOVER)
gameover++;
else if (board->flags & TETF_NEXTLEVEL)
nextlevel++;
}
}
if ((NoWaitLevel) || (nextlevel == (i - gameover))) {
for (i = 0; i < Players; i++) {
if (Controls[i].cd_Task) {
board = Controls[i].cd_Board;
if (board->flags & TETF_NEXTLEVEL) {
StartLevel(board, board->clevel + 1);
}
}
}
}
}
} /* end Wait Loop */
}
#define next event_handler
BOOL
StartOfGame(void)
{
struct ControlData *c;
int x, y;
struct Task *ThisTask = FindTask(NULL);
for (c = &Controls[0], NumPlayers = 0; NumPlayers < Players; c++, NumPlayers++) {
c->cd_Board = NULL;
c->cd_Task = CreateTask("Tetris_ConTask", 0, TaskEntries[NumPlayers], STACK_SIZE);
if (!c->cd_Task) break;
c->cd_Board = NewBoard(Window->RPort, Window->BorderLeft + BSize + (PWidth + BSize * 2) * NumPlayers, heights[1]);
if (!c->cd_Board) {
DeleteTask(c->cd_Task);
c->cd_Task = NULL;
break;
}
printf("Player %d uses %s\n", NumPlayers, ControlUsage[NumPlayers]);
c->cd_Parent = ThisTask;
c->cd_MsgPort = tetris_MsgPort;
c->cd_State = 0;
c->cd_Keys = ControlKeys[NumPlayers];
c->cd_Task->tc_UserData = c;
Signal(c->cd_Task, SIGBREAKF_CTRL_F); /* Signal task, the data is ready */
}
if (NumPlayers != Players) {
x = NumPlayers * (PWidth + BSize * 2) + Screen->WBorLeft + Screen->WBorRight;
y = heights[0] = PHeight + Screen->WBorBottom + heights[1] + BSize;
ChangeWindowBox(Window, (Screen->Width - x) / 2, (Screen->Height - y) / 2, x, y);
}
return NumPlayers;
}
void
EndOfGame(void)
{
int i;
for (i = 0; i < NumPlayers; i++) { /* Make sure everything is freed */
if (Controls[i].cd_Board) {
printf("FreeBoard - this shouldn't have happened.\n");
FreeBoard(Controls[i].cd_Board);
}
if (Controls[i].cd_Task) {
printf("DeleteTask - this shouldn't have happened.\n");
DeleteTask(Controls[i].cd_Task);
}
}
}
void
tetris(void)
{
if (InitTetrisImages(Screen->BitMap.Depth, XSize, YSize)) {
if (StartOfGame()) { /* Add Players */
next();
EndOfGame();
}
FreeTetrisImages(Screen->BitMap.Depth, XSize, YSize);
}
}
#undef next
#define next tetris
struct Window *
tetris_window(void)
{
struct Window *w;
WORD zoom[4];
heights[1] = Screen->WBorTop + Screen->Font->ta_YSize + 1 + YSize * 4;
heights[0] = PHeight + Screen->WBorBottom + heights[1] + BSize;
zoom[3] = heights[1];
zoom[2] = Players * (PWidth + (BSize * 2)) + Screen->WBorLeft + Screen->WBorRight;
zoom[1] = (Screen->Height - heights[0]) / 2;
zoom[0] = (Screen->Width - zoom[2]) / 2;
w = OpenWindowTags(NULL,
WA_Title, "Tetris",
WA_ScreenTitle, "Tetris",
WA_Left, zoom[0],
WA_Top, zoom[1],
WA_Width,zoom[2],
WA_Height, heights[0],
WA_Zoom, zoom,
WA_Gadgets, Gadgets,
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE,// | WFLG_GIMMEZEROZERO,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_IDCMPUPDATE | IDCMP_CHANGEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_REFRESHWINDOW,
TAG_DONE
);
return w;
}
void
window(void)
{
Window = tetris_window();
if (Window) {
next();
CloseWindow(Window);
}
}
#undef next
#define next window
void
screen(void)
{
Screen = LockPubScreen(NULL);
if (Screen) {
next();
UnlockPubScreen(NULL, Screen);
}
}
#undef next
#define next screen
void
timer(void)
{
timer_MsgPort = CreateMsgPort();
if (timer_MsgPort) {
timer_IORequest = (struct timerequest *)CreateIORequest(timer_MsgPort, sizeof(struct timerequest));
if (timer_IORequest) {
if (!OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_IORequest, 0L)) {
timer_IORequest->tr_node.io_Command = TR_ADDREQUEST;
timer_IORequest->tr_time.tv_secs = 0;
timer_IORequest->tr_time.tv_micro = UPDATE_TIME;
SendIO((struct IORequest *)timer_IORequest);
next();
if (!CheckIO((struct IORequest *) timer_IORequest)) {
AbortIO((struct IORequest *) timer_IORequest);
WaitIO((struct IORequest *) timer_IORequest);
}
CloseDevice((struct IORequest *) timer_IORequest);
} else printf("No timer.device!\n");
DeleteIORequest((struct IORequest *) timer_IORequest);
} else printf("No timer io request!\n");
DeleteMsgPort(timer_MsgPort);
} else printf("No timer msg port!\n");
}
#undef next
#define next timer
void
msgport(void)
{
tetris_MsgPort = CreateMsgPort();
if (tetris_MsgPort) {
tetris_MsgPort->mp_Node.ln_Name = TETRIS_PORT;
next();
DeleteMsgPort(tetris_MsgPort);
} else printf("No player msg port!\n");
}
#undef next
#define next msgport
BOOL
ParseArgs(void)
{
struct RDArgs *RDArgs;
char Template[] = "PLAYERS/N,LEVEL/N,DEPTH/N,XSIZE/N,YSIZE/N,BORDER/N,NOWAIT/S";
LONG Args[] = {0, 0, 0, 0, 0, 0, 0};
RDArgs = ReadArgs(Template, Args, NULL);
if (RDArgs) {
if (Args[0]) { Players = *(LONG *)Args[0]; if (Players > MAX_PLAYERS) Players = MAX_PLAYERS; }
if (Args[1]) Level = *(LONG *)Args[1];
if (Args[2]) Depth = *(LONG *)Args[2];
if (Args[3]) XSize = *(LONG *)Args[3];
if (Args[4]) YSize = *(LONG *)Args[4];
if (Args[5]) BSize = *(LONG *)Args[5];
NoWaitLevel = Args[6];
PWidth = (PFWIDTH * XSize);
PHeight = (PFHEIGHT * YSize);
FreeArgs(RDArgs);
return TRUE;
}
return FALSE;
}
int
main(void)
{
printf("Tetris version 1.0\nCopyright (C) 1992 Trevor Smigiel.\n");
if (ParseArgs()) {
if(!(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
next();
} else PrintFault(IoErr(), "ReadArgs");
return 0;
}